Hey Ray, Just for grins- ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1; > } catch {} In that dead catch, expand it and put a Console.WriteLine("some error"); Then put a breakpoint just to make sure you aren't silently ignoring an exception. I'd also check for this anywhere else you have this type of code. Empty catches are generally bad, even if you do not really care if the exception occurs. I found putting a console write like above or some other logging mechanism has saved me a lot of pain. -Brad Murry
| Group: DynoMotion |
Message: 6472 |
From: brad murry |
Date: 1/13/2013 |
| Subject: Re: To Invoke, Or Not To Invoke.... |
Just wanted to clarify that callbacks from the interpreter are not on the main thread, they are fired from the interpreter's worker thread.
| Group: DynoMotion |
Message: 6473 |
From: himykabibble |
Date: 1/13/2013 |
| Subject: Re: To Invoke, Or Not To Invoke.... |
Brad,
I just stripped down what I pasted into the message. The catch is not empty, and the call is working, and returning the correct value. I believe what is happening is the invoke copies the stack frame, or perhaps just creates a completely new one, executes the code, but does not copy the local variables back to the original frame when the invoke ends, so any local variables that get set in the invoke are lost. If I put the return value into a public variable, then it works correctly. Not ideal, if the function can be called from multiple places simultaneously, but that's not the case here. So I at least have one work-around, though I want to find a cleaner one.
I am NOT doing invokes on methods that are only reading variables, and not communicating with the board. It seems to be working fine like that. Do you think that's OK? Seems to me reads should be perfectly thread-safe, no?
I feel MUCH better about the state of the threading in the app now. It all makes sense, and is much cleaner than it was before. Between me, you and Tom working on various specific pieces of it a year ago, it had some pretty gnarly stuff in it, but I think today I got it pretty well cleaned up, and it's now nice and regular and orderly.
Regards,
Ray L.
--- In DynoMotion@yahoogroups.com, brad murry wrote:
>
>
> Hey Ray, Just for grins- ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1;
> > } catch {} In that dead catch, expand it and put a Console.WriteLine("some error"); Then put a breakpoint just to make sure you aren't silently ignoring an exception. I'd also check for this anywhere else you have this type of code. Empty catches are generally bad, even if you do not really care if the exception occurs. I found putting a console write like above or some other logging mechanism has saved me a lot of pain. -Brad Murry
> To: DynoMotion@yahoogroups.com
> From: jagboy1964@...
> Date: Mon, 14 Jan 2013 06:03:10 +0000
> Subject: [DynoMotion] Re: To Invoke, Or Not To Invoke....
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> I've got most of it working nicely now, with the invokes done in my dotNet wrapper. It seems to be quite stable, and doing the invokes in the wrapper is a lot simpler. If I can just find a way to make the return values below work, I'll be in business.
>
>
>
> Sure seems odd to me that I can't seem to write to the ret variable, when everything else seems to work fine.
>
>
>
> Regards,
>
> Ray L.
>
>
>
> --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
>
> >
>
> > Seems so close.... As a test, I've implemented some of my dotNet wrapper functions so they do the invoke. This seems to be very stable, and works well, except.... I can't get the return values. As an example:
>
> >
>
> > public Boolean SpindleIsOnCW()
>
> > {
>
> > Boolean ret = false;
>
> >
>
> > UpdateDocument(new Action(delegate()
>
> > {
>
> > if (Connected && KMConnected())
>
> > try
>
> > {
>
> > ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1;
>
> > } catch {}
>
> > }
>
> > ));
>
> > return ret;
>
> > }
>
> >
>
> > ret always returns false, even when GetKFlopBitState returns true.
>
> >
>
> > Regards,
>
> > Ray L.
>
> >
>
> >
>
> > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
>
> > >
>
> > > Brad,
>
> > >
>
> > > I've been playing with this, and I think I'm starting to get a handle on it, and did find some mistakes where a few things were being called from the wrong thread. It is working better now - not 100%, but close, with a few very brute force fixes just to prove the point.
>
> > >
>
> > > So, I think I know how to clean it up.... mostly. I am curious though what is the best approach. I can, of course, always invoke when calling dotNet members from other threads, but I wonder if it wouldn't be cleaner to do the invoke with the methods in my wrapper instead, so the other threads don't need to worry about the housekeeping. Will that work? Would it be higher overhead? It's not clear to me what the overhead of invoking is. Isn't it basically just waiting to get a lock on the target object, which should be fairly low-overhead? Or is there more to it than that?
>
> > >
>
> > > Regards,
>
> > > Ray L.
>
> > >
>
> > > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
>
> > > >
>
> > > > Brad,
>
> > > >
>
> > > > That's exactly what I'm doing. But the question is, *where* do I need to do it. I've done it at what are, to me, the obvious places (all calls from the worker thread, for example), but now have a problem where I didn't before, so I've obviously missed something.
>
> > > >
>
> > > > I'm assuming both my "main page" code, and my "wrapper" for dotNet run in the GUI thread. The worker threads should then be invoking for any access to my dotNet wrapper methods, right? But is it necessary to invoke for all of them? Many are doing nothing by reading properties and returning them, without any interaction with the DLLs. I assume those can safely NOT be invoked, right? Can the invokes be "hidden" in my wrapper methods, so they can be called from anywhere?
>
> > > >
>
> > > > Regards,
>
> > > > Ray L.
>
> > > >
>
> > > >
>
> > > > --- In DynoMotion@yahoogroups.com, Brad Murry wrote:
>
> > > > >
>
> > > > > Hello Ray
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > I always used something like this for winforms where there was a
>
> > > > > possibility of updating controls from a thread other than the main STA
>
> > > > > Thread.
>
> > > > >
>
> > > > > **Note that this method is living inside a UI component like the main form
>
> > > > > or a usercontrol.
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > If using .net 2.0 and lower, you have to create a delegate to fire off
>
> > > > > asynchronously.
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > public void InvokeUpdateControls()
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > if (this.InvokeRequired)
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > this.Invoke(new UpdateControlsDelegate(UpdateControls));
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > > else
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > UpdateControls();
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > Of course with .net 3.5 and up you get anonymous methods so.
>
> > > > >
>
> > > > > public void InvokeUpdateControls()
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > if (this.InvokeRequired)
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > this.Invoke(new Action(delegate(){UpdateControls();}));
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > > else
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > UpdateControls();
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > Good thing the DM libraries are built on 3.5!
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > -Brad Murry
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > From: DynoMotion@yahoogroups.com [mailto:DynoMotion@yahoogroups.com] On
>
> > > > > Behalf Of himykabibble
>
> > > > > Sent: Sunday, January 13, 2013 5:30 PM
>
> > > > > To: DynoMotion@yahoogroups.com
>
> > > > > Subject: [DynoMotion] To Invoke, Or Not To Invoke....
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > I've got my app converted to use mostly MainStatus, and it at least
>
> > > > > *appears* I'm getting slightly smoother operation of the DROs. However, I
>
> > > > > seem to have created a thread hazard or two, a the app now hangs when I do
>
> > > > > MDI. So, the question is:
>
> > > > >
>
> > > > > How do I know when it is necessary to do an invoke? The hangs appear to be
>
> > > > > occurring withing KMotion.dll, in code that appears to be waiting to obtain
>
> > > > > a lock. The changes I've made today are limited to code that is interacting
>
> > > > > with dotNet, and appears to *only* affect MDIs, which are launched from the
>
> > > > > GUI thread based on on-screen button presses, while most accesses to dotNet
>
> > > > > are coming from a worker thread. So, I assume it's those two thread stomping
>
> > > > > on each other causing the problem. The worker thread accesses are always
>
> > > > > invoked.
>
> > > > >
>
> > > > > Any tips on how to figure out what I've screwed up?
>
> > > > >
>
> > > > > Regards,
>
> > > > > Ray L.
>
> > > > >
>
> > > >
>
> > >
>
> >
>
|
|
| Group: DynoMotion |
Message: 6474 |
From: himykabibble |
Date: 1/13/2013 |
| Subject: Re: To Invoke, Or Not To Invoke.... |
Brad,
Yeah, I had that covered already. The callbacks are simply writing data structures using locks, so no problems there.
Regards,
Ray L.
--- In DynoMotion@yahoogroups.com, brad murry wrote:
>
>
> Just wanted to clarify that callbacks from the interpreter are not on the main thread, they are fired from the interpreter's worker thread.
> To: DynoMotion@yahoogroups.com
> From: jagboy1964@...
> Date: Mon, 14 Jan 2013 02:24:09 +0000
> Subject: [DynoMotion] Re: To Invoke, Or Not To Invoke....
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> Brad,
>
>
>
> I've been playing with this, and I think I'm starting to get a handle on it, and did find some mistakes where a few things were being called from the wrong thread. It is working better now - not 100%, but close, with a few very brute force fixes just to prove the point.
>
>
>
> So, I think I know how to clean it up.... mostly. I am curious though what is the best approach. I can, of course, always invoke when calling dotNet members from other threads, but I wonder if it wouldn't be cleaner to do the invoke with the methods in my wrapper instead, so the other threads don't need to worry about the housekeeping. Will that work? Would it be higher overhead? It's not clear to me what the overhead of invoking is. Isn't it basically just waiting to get a lock on the target object, which should be fairly low-overhead? Or is there more to it than that?
>
>
>
> Regards,
>
> Ray L.
>
>
>
> --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
>
> >
>
> > Brad,
>
> >
>
> > That's exactly what I'm doing. But the question is, *where* do I need to do it. I've done it at what are, to me, the obvious places (all calls from the worker thread, for example), but now have a problem where I didn't before, so I've obviously missed something.
>
> >
>
> > I'm assuming both my "main page" code, and my "wrapper" for dotNet run in the GUI thread. The worker threads should then be invoking for any access to my dotNet wrapper methods, right? But is it necessary to invoke for all of them? Many are doing nothing by reading properties and returning them, without any interaction with the DLLs. I assume those can safely NOT be invoked, right? Can the invokes be "hidden" in my wrapper methods, so they can be called from anywhere?
>
> >
>
> > Regards,
>
> > Ray L.
>
> >
>
> >
>
> > --- In DynoMotion@yahoogroups.com, Brad Murry wrote:
>
> > >
>
> > > Hello Ray
>
> > >
>
> > >
>
> > >
>
> > > I always used something like this for winforms where there was a
>
> > > possibility of updating controls from a thread other than the main STA
>
> > > Thread.
>
> > >
>
> > > **Note that this method is living inside a UI component like the main form
>
> > > or a usercontrol.
>
> > >
>
> > >
>
> > >
>
> > >
>
> > >
>
> > > If using .net 2.0 and lower, you have to create a delegate to fire off
>
> > > asynchronously.
>
> > >
>
> > >
>
> > >
>
> > > public void InvokeUpdateControls()
>
> > >
>
> > > {
>
> > >
>
> > > if (this.InvokeRequired)
>
> > >
>
> > > {
>
> > >
>
> > > this.Invoke(new UpdateControlsDelegate(UpdateControls));
>
> > >
>
> > > }
>
> > >
>
> > > else
>
> > >
>
> > > {
>
> > >
>
> > > UpdateControls();
>
> > >
>
> > > }
>
> > >
>
> > > }
>
> > >
>
> > >
>
> > >
>
> > >
>
> > >
>
> > > Of course with .net 3.5 and up you get anonymous methods so.
>
> > >
>
> > > public void InvokeUpdateControls()
>
> > >
>
> > > {
>
> > >
>
> > > if (this.InvokeRequired)
>
> > >
>
> > > {
>
> > >
>
> > > this.Invoke(new Action(delegate(){UpdateControls();}));
>
> > >
>
> > > }
>
> > >
>
> > > else
>
> > >
>
> > > {
>
> > >
>
> > > UpdateControls();
>
> > >
>
> > > }
>
> > >
>
> > > }
>
> > >
>
> > >
>
> > >
>
> > >
>
> > >
>
> > > Good thing the DM libraries are built on 3.5!
>
> > >
>
> > >
>
> > >
>
> > > -Brad Murry
>
> > >
>
> > >
>
> > >
>
> > > From: DynoMotion@yahoogroups.com [mailto:DynoMotion@yahoogroups.com] On
>
> > > Behalf Of himykabibble
>
> > > Sent: Sunday, January 13, 2013 5:30 PM
>
> > > To: DynoMotion@yahoogroups.com
>
> > > Subject: [DynoMotion] To Invoke, Or Not To Invoke....
>
> > >
>
> > >
>
> > >
>
> > >
>
> > >
>
> > > I've got my app converted to use mostly MainStatus, and it at least
>
> > > *appears* I'm getting slightly smoother operation of the DROs. However, I
>
> > > seem to have created a thread hazard or two, a the app now hangs when I do
>
> > > MDI. So, the question is:
>
> > >
>
> > > How do I know when it is necessary to do an invoke? The hangs appear to be
>
> > > occurring withing KMotion.dll, in code that appears to be waiting to obtain
>
> > > a lock. The changes I've made today are limited to code that is interacting
>
> > > with dotNet, and appears to *only* affect MDIs, which are launched from the
>
> > > GUI thread based on on-screen button presses, while most accesses to dotNet
>
> > > are coming from a worker thread. So, I assume it's those two thread stomping
>
> > > on each other causing the problem. The worker thread accesses are always
>
> > > invoked.
>
> > >
>
> > > Any tips on how to figure out what I've screwed up?
>
> > >
>
> > > Regards,
>
> > > Ray L.
>
> > >
>
> >
>
|
|
| Group: DynoMotion |
Message: 6475 |
From: brad murry |
Date: 1/14/2013 |
| Subject: Re: To Invoke, Or Not To Invoke.... |
Ahh of course! your variable is out of scope inside the anonymous keeps method (your surrounding function returns before the invoke is complete).
I must have not looked at the whole thing before, as it is quite obvious now. ;)
Either use a delgate, begininvoke it in your invoke block and update the value in the delegate's endinvoke callback or call a function in your anonymous method that sets the value rather than returning a variable value.
There are a couple more options that may be more elegant, but are less straightforward.
Sent from my Windows Phone
Brad,
I just stripped down what I pasted into the message. The catch is not empty, and the call is working, and returning the correct value. I believe what is happening is the invoke copies the stack frame, or perhaps just creates a completely new one, executes the
code, but does not copy the local variables back to the original frame when the invoke ends, so any local variables that get set in the invoke are lost. If I put the return value into a public variable, then it works correctly. Not ideal, if the function can
be called from multiple places simultaneously, but that's not the case here. So I at least have one work-around, though I want to find a cleaner one.
I am NOT doing invokes on methods that are only reading variables, and not communicating with the board. It seems to be working fine like that. Do you think that's OK? Seems to me reads should be perfectly thread-safe, no?
I feel MUCH better about the state of the threading in the app now. It all makes sense, and is much cleaner than it was before. Between me, you and Tom working on various specific pieces of it a year ago, it had some pretty gnarly stuff in it, but I think today
I got it pretty well cleaned up, and it's now nice and regular and orderly.
Regards,
Ray L.
--- In DynoMotion@yahoogroups.com, brad murry wrote:
>
>
> Hey Ray, Just for grins- ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1;
> > } catch {} In that dead catch, expand it and put a Console.WriteLine("some error"); Then put a breakpoint just to make sure you aren't silently ignoring an exception. I'd also check for this anywhere else you have this type of code. Empty catches are generally
bad, even if you do not really care if the exception occurs. I found putting a console write like above or some other logging mechanism has saved me a lot of pain. -Brad Murry
> To: DynoMotion@yahoogroups.com
> From: jagboy1964@...
> Date: Mon, 14 Jan 2013 06:03:10 +0000
> Subject: [DynoMotion] Re: To Invoke, Or Not To Invoke....
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
> I've got most of it working nicely now, with the invokes done in my dotNet wrapper. It seems to be quite stable, and doing the invokes in the wrapper is a lot simpler. If I can just find a way to make the return values below work, I'll be in business.
>
>
>
> Sure seems odd to me that I can't seem to write to the ret variable, when everything else seems to work fine.
>
>
>
> Regards,
>
> Ray L.
>
>
>
> --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
>
> >
>
> > Seems so close.... As a test, I've implemented some of my dotNet wrapper functions so they do the invoke. This seems to be very stable, and works well, except.... I can't get the return values. As an example:
>
> >
>
> > public Boolean SpindleIsOnCW()
>
> > {
>
> > Boolean ret = false;
>
> >
>
> > UpdateDocument(new Action(delegate()
>
> > {
>
> > if (Connected && KMConnected())
>
> > try
>
> > {
>
> > ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1;
>
> > } catch {}
>
> > }
>
> > ));
>
> > return ret;
>
> > }
>
> >
>
> > ret always returns false, even when GetKFlopBitState returns true.
>
> >
>
> > Regards,
>
> > Ray L.
>
> >
>
> >
>
> > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
>
> > >
>
> > > Brad,
>
> > >
>
> > > I've been playing with this, and I think I'm starting to get a handle on it, and did find some mistakes where a few things were being called from the wrong thread. It is working better now - not 100%, but close, with a few very brute force fixes just
to prove the point.
>
> > >
>
> > > So, I think I know how to clean it up.... mostly. I am curious though what is the best approach. I can, of course, always invoke when calling dotNet members from other threads, but I wonder if it wouldn't be cleaner to do the invoke with the methods in
my wrapper instead, so the other threads don't need to worry about the housekeeping. Will that work? Would it be higher overhead? It's not clear to me what the overhead of invoking is. Isn't it basically just waiting to get a lock on the target object, which
should be fairly low-overhead? Or is there more to it than that?
>
> > >
>
> > > Regards,
>
> > > Ray L.
>
> > >
>
> > > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
>
> > > >
>
> > > > Brad,
>
> > > >
>
> > > > That's exactly what I'm doing. But the question is, *where* do I need to do it. I've done it at what are, to me, the obvious places (all calls from the worker thread, for example), but now have a problem where I didn't before, so I've obviously missed
something.
>
> > > >
>
> > > > I'm assuming both my "main page" code, and my "wrapper" for dotNet run in the GUI thread. The worker threads should then be invoking for any access to my dotNet wrapper methods, right? But is it necessary to invoke for all of them? Many are doing nothing
by reading properties and returning them, without any interaction with the DLLs. I assume those can safely NOT be invoked, right? Can the invokes be "hidden" in my wrapper methods, so they can be called from anywhere?
>
> > > >
>
> > > > Regards,
>
> > > > Ray L.
>
> > > >
>
> > > >
>
> > > > --- In DynoMotion@yahoogroups.com, Brad Murry wrote:
>
> > > > >
>
> > > > > Hello Ray
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > I always used something like this for winforms where there was a
>
> > > > > possibility of updating controls from a thread other than the main STA
>
> > > > > Thread.
>
> > > > >
>
> > > > > **Note that this method is living inside a UI component like the main form
>
> > > > > or a usercontrol.
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > If using .net 2.0 and lower, you have to create a delegate to fire off
>
> > > > > asynchronously.
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > public void InvokeUpdateControls()
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > if (this.InvokeRequired)
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > this.Invoke(new UpdateControlsDelegate(UpdateControls));
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > > else
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > UpdateControls();
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > Of course with .net 3.5 and up you get anonymous methods so.
>
> > > > >
>
> > > > > public void InvokeUpdateControls()
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > if (this.InvokeRequired)
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > this.Invoke(new Action(delegate(){UpdateControls();}));
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > > else
>
> > > > >
>
> > > > > {
>
> > > > >
>
> > > > > UpdateControls();
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > > }
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > Good thing the DM libraries are built on 3.5!
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > -Brad Murry
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > From: DynoMotion@yahoogroups.com [mailto:DynoMotion@yahoogroups.com] On
>
> > > > > Behalf Of himykabibble
>
> > > > > Sent: Sunday, January 13, 2013 5:30 PM
>
> > > > > To: DynoMotion@yahoogroups.com
>
> > > > > Subject: [DynoMotion] To Invoke, Or Not To Invoke....
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > >
>
> > > > > I've got my app converted to use mostly MainStatus, and it at least
>
> > > > > *appears* I'm getting slightly smoother operation of the DROs. However, I
>
> > > > > seem to have created a thread hazard or two, a the app now hangs when I do
>
> > > > > MDI. So, the question is:
>
> > > > >
>
> > > > > How do I know when it is necessary to do an invoke? The hangs appear to be
>
> > > > > occurring withing KMotion.dll, in code that appears to be waiting to obtain
>
> > > > > a lock. The changes I've made today are limited to code that is interacting
>
> > > > > with dotNet, and appears to *only* affect MDIs, which are launched from the
>
> > > > > GUI thread based on on-screen button presses, while most accesses to dotNet
>
> > > > > are coming from a worker thread. So, I assume it's those two thread stomping
>
> > > > > on each other causing the problem. The worker thread accesses are always
>
> > > > > invoked.
>
> > > > >
>
> > > > > Any tips on how to figure out what I've screwed up?
>
> > > > >
>
> > > > > Regards,
>
> > > > > Ray L.
>
> > > > >
>
> > > >
>
> > >
>
> >
>
|
|
| Group: DynoMotion |
Message: 6476 |
From: himykabibble |
Date: 1/14/2013 |
| Subject: Re: To Invoke, Or Not To Invoke.... |
Brad,
None of those options seem fundamentally any more elegant, and are more work, than simply having the anonymous function write its result to a public variable, as I did in my test last night.
Regards,
Ray L.
--- In DynoMotion@yahoogroups.com, brad murry wrote:
>
> Ahh of course! your variable is out of scope inside the anonymous keeps method (your surrounding function returns before the invoke is complete).
>
> I must have not looked at the whole thing before, as it is quite obvious now. ;)
>
> Either use a delgate, begininvoke it in your invoke block and update the value in the delegate's endinvoke callback or call a function in your anonymous method that sets the value rather than returning a variable value.
>
>
> There are a couple more options that may be more elegant, but are less straightforward.
>
> Sent from my Windows Phone
> ________________________________
> From: himykabibble
> Sent: â1/â14/â2013 12:37 AM
> To: DynoMotion@yahoogroups.com
> Subject: [DynoMotion] Re: To Invoke, Or Not To Invoke....
>
> Brad,
>
> I just stripped down what I pasted into the message. The catch is not empty, and the call is working, and returning the correct value. I believe what is happening is the invoke copies the stack frame, or perhaps just creates a completely new one, executes the code, but does not copy the local variables back to the original frame when the invoke ends, so any local variables that get set in the invoke are lost. If I put the return value into a public variable, then it works correctly. Not ideal, if the function can be called from multiple places simultaneously, but that's not the case here. So I at least have one work-around, though I want to find a cleaner one.
>
> I am NOT doing invokes on methods that are only reading variables, and not communicating with the board. It seems to be working fine like that. Do you think that's OK? Seems to me reads should be perfectly thread-safe, no?
>
> I feel MUCH better about the state of the threading in the app now. It all makes sense, and is much cleaner than it was before. Between me, you and Tom working on various specific pieces of it a year ago, it had some pretty gnarly stuff in it, but I think today I got it pretty well cleaned up, and it's now nice and regular and orderly.
>
> Regards,
> Ray L.
>
> --- In DynoMotion@yahoogroups.com, brad murry wrote:
> >
> >
> > Hey Ray, Just for grins- ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1;
> > > } catch {} In that dead catch, expand it and put a Console.WriteLine("some error"); Then put a breakpoint just to make sure you aren't silently ignoring an exception. I'd also check for this anywhere else you have this type of code. Empty catches are generally bad, even if you do not really care if the exception occurs. I found putting a console write like above or some other logging mechanism has saved me a lot of pain. -Brad Murry
> > To: DynoMotion@yahoogroups.com
> > From: jagboy1964@
> > Date: Mon, 14 Jan 2013 06:03:10 +0000
> > Subject: [DynoMotion] Re: To Invoke, Or Not To Invoke....
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > I've got most of it working nicely now, with the invokes done in my dotNet wrapper. It seems to be quite stable, and doing the invokes in the wrapper is a lot simpler. If I can just find a way to make the return values below work, I'll be in business.
> >
> >
> >
> > Sure seems odd to me that I can't seem to write to the ret variable, when everything else seems to work fine.
> >
> >
> >
> > Regards,
> >
> > Ray L.
> >
> >
> >
> > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
> >
> > >
> >
> > > Seems so close.... As a test, I've implemented some of my dotNet wrapper functions so they do the invoke. This seems to be very stable, and works well, except.... I can't get the return values. As an example:
> >
> > >
> >
> > > public Boolean SpindleIsOnCW()
> >
> > > {
> >
> > > Boolean ret = false;
> >
> > >
> >
> > > UpdateDocument(new Action(delegate()
> >
> > > {
> >
> > > if (Connected && KMConnected())
> >
> > > try
> >
> > > {
> >
> > > ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1;
> >
> > > } catch {}
> >
> > > }
> >
> > > ));
> >
> > > return ret;
> >
> > > }
> >
> > >
> >
> > > ret always returns false, even when GetKFlopBitState returns true.
> >
> > >
> >
> > > Regards,
> >
> > > Ray L.
> >
> > >
> >
> > >
> >
> > > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
> >
> > > >
> >
> > > > Brad,
> >
> > > >
> >
> > > > I've been playing with this, and I think I'm starting to get a handle on it, and did find some mistakes where a few things were being called from the wrong thread. It is working better now - not 100%, but close, with a few very brute force fixes just to prove the point.
> >
> > > >
> >
> > > > So, I think I know how to clean it up.... mostly. I am curious though what is the best approach. I can, of course, always invoke when calling dotNet members from other threads, but I wonder if it wouldn't be cleaner to do the invoke with the methods in my wrapper instead, so the other threads don't need to worry about the housekeeping. Will that work? Would it be higher overhead? It's not clear to me what the overhead of invoking is. Isn't it basically just waiting to get a lock on the target object, which should be fairly low-overhead? Or is there more to it than that?
> >
> > > >
> >
> > > > Regards,
> >
> > > > Ray L.
> >
> > > >
> >
> > > > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
> >
> > > > >
> >
> > > > > Brad,
> >
> > > > >
> >
> > > > > That's exactly what I'm doing. But the question is, *where* do I need to do it. I've done it at what are, to me, the obvious places (all calls from the worker thread, for example), but now have a problem where I didn't before, so I've obviously missed something.
> >
> > > > >
> >
> > > > > I'm assuming both my "main page" code, and my "wrapper" for dotNet run in the GUI thread. The worker threads should then be invoking for any access to my dotNet wrapper methods, right? But is it necessary to invoke for all of them? Many are doing nothing by reading properties and returning them, without any interaction with the DLLs. I assume those can safely NOT be invoked, right? Can the invokes be "hidden" in my wrapper methods, so they can be called from anywhere?
> >
> > > > >
> >
> > > > > Regards,
> >
> > > > > Ray L.
> >
> > > > >
> >
> > > > >
> >
> > > > > --- In DynoMotion@yahoogroups.com, Brad Murry wrote:
> >
> > > > > >
> >
> > > > > > Hello Ray
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > I always used something like this for winforms where there was a
> >
> > > > > > possibility of updating controls from a thread other than the main STA
> >
> > > > > > Thread.
> >
> > > > > >
> >
> > > > > > **Note that this method is living inside a UI component like the main form
> >
> > > > > > or a usercontrol.
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > If using .net 2.0 and lower, you have to create a delegate to fire off
> >
> > > > > > asynchronously.
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > public void InvokeUpdateControls()
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > if (this.InvokeRequired)
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > this.Invoke(new UpdateControlsDelegate(UpdateControls));
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > > else
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > UpdateControls();
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > Of course with .net 3.5 and up you get anonymous methods so.
> >
> > > > > >
> >
> > > > > > public void InvokeUpdateControls()
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > if (this.InvokeRequired)
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > this.Invoke(new Action(delegate(){UpdateControls();}));
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > > else
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > UpdateControls();
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > Good thing the DM libraries are built on 3.5!
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > -Brad Murry
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > From: DynoMotion@yahoogroups.com [mailto:DynoMotion@yahoogroups.com] On
> >
> > > > > > Behalf Of himykabibble
> >
> > > > > > Sent: Sunday, January 13, 2013 5:30 PM
> >
> > > > > > To: DynoMotion@yahoogroups.com
> >
> > > > > > Subject: [DynoMotion] To Invoke, Or Not To Invoke....
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > I've got my app converted to use mostly MainStatus, and it at least
> >
> > > > > > *appears* I'm getting slightly smoother operation of the DROs. However, I
> >
> > > > > > seem to have created a thread hazard or two, a the app now hangs when I do
> >
> > > > > > MDI. So, the question is:
> >
> > > > > >
> >
> > > > > > How do I know when it is necessary to do an invoke? The hangs appear to be
> >
> > > > > > occurring withing KMotion.dll, in code that appears to be waiting to obtain
> >
> > > > > > a lock. The changes I've made today are limited to code that is interacting
> >
> > > > > > with dotNet, and appears to *only* affect MDIs, which are launched from the
> >
> > > > > > GUI thread based on on-screen button presses, while most accesses to dotNet
> >
> > > > > > are coming from a worker thread. So, I assume it's those two thread stomping
> >
> > > > > > on each other causing the problem. The worker thread accesses are always
> >
> > > > > > invoked.
> >
> > > > > >
> >
> > > > > > Any tips on how to figure out what I've screwed up?
> >
> > > > > >
> >
> > > > > > Regards,
> >
> > > > > > Ray L.
> >
> > > > > >
> >
> > > > >
> >
> > > >
> >
> > >
> >
>
|
|
| Group: DynoMotion |
Message: 6477 |
From: himykabibble |
Date: 1/14/2013 |
| Subject: Re: To Invoke, Or Not To Invoke.... |
Brad,
Would you agree that calling dotNet methods that do not require communications with the board (for example, getting current tool number from the interpreter), should be thread-safe, and not require invokes?
Regards,
Ray L.
--- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
>
> Brad,
>
> None of those options seem fundamentally any more elegant, and are more work, than simply having the anonymous function write its result to a public variable, as I did in my test last night.
>
> Regards,
> Ray L.
>
> --- In DynoMotion@yahoogroups.com, brad murry wrote:
> >
> > Ahh of course! your variable is out of scope inside the anonymous keeps method (your surrounding function returns before the invoke is complete).
> >
> > I must have not looked at the whole thing before, as it is quite obvious now. ;)
> >
> > Either use a delgate, begininvoke it in your invoke block and update the value in the delegate's endinvoke callback or call a function in your anonymous method that sets the value rather than returning a variable value.
> >
> >
> > There are a couple more options that may be more elegant, but are less straightforward.
> >
> > Sent from my Windows Phone
> > ________________________________
> > From: himykabibble
> > Sent: â1/â14/â2013 12:37 AM
> > To: DynoMotion@yahoogroups.com
> > Subject: [DynoMotion] Re: To Invoke, Or Not To Invoke....
> >
> > Brad,
> >
> > I just stripped down what I pasted into the message. The catch is not empty, and the call is working, and returning the correct value. I believe what is happening is the invoke copies the stack frame, or perhaps just creates a completely new one, executes the code, but does not copy the local variables back to the original frame when the invoke ends, so any local variables that get set in the invoke are lost. If I put the return value into a public variable, then it works correctly. Not ideal, if the function can be called from multiple places simultaneously, but that's not the case here. So I at least have one work-around, though I want to find a cleaner one.
> >
> > I am NOT doing invokes on methods that are only reading variables, and not communicating with the board. It seems to be working fine like that. Do you think that's OK? Seems to me reads should be perfectly thread-safe, no?
> >
> > I feel MUCH better about the state of the threading in the app now. It all makes sense, and is much cleaner than it was before. Between me, you and Tom working on various specific pieces of it a year ago, it had some pretty gnarly stuff in it, but I think today I got it pretty well cleaned up, and it's now nice and regular and orderly.
> >
> > Regards,
> > Ray L.
> >
> > --- In DynoMotion@yahoogroups.com, brad murry wrote:
> > >
> > >
> > > Hey Ray, Just for grins- ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1;
> > > > } catch {} In that dead catch, expand it and put a Console.WriteLine("some error"); Then put a breakpoint just to make sure you aren't silently ignoring an exception. I'd also check for this anywhere else you have this type of code. Empty catches are generally bad, even if you do not really care if the exception occurs. I found putting a console write like above or some other logging mechanism has saved me a lot of pain. -Brad Murry
> > > To: DynoMotion@yahoogroups.com
> > > From: jagboy1964@
> > > Date: Mon, 14 Jan 2013 06:03:10 +0000
> > > Subject: [DynoMotion] Re: To Invoke, Or Not To Invoke....
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > > I've got most of it working nicely now, with the invokes done in my dotNet wrapper. It seems to be quite stable, and doing the invokes in the wrapper is a lot simpler. If I can just find a way to make the return values below work, I'll be in business.
> > >
> > >
> > >
> > > Sure seems odd to me that I can't seem to write to the ret variable, when everything else seems to work fine.
> > >
> > >
> > >
> > > Regards,
> > >
> > > Ray L.
> > >
> > >
> > >
> > > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
> > >
> > > >
> > >
> > > > Seems so close.... As a test, I've implemented some of my dotNet wrapper functions so they do the invoke. This seems to be very stable, and works well, except.... I can't get the return values. As an example:
> > >
> > > >
> > >
> > > > public Boolean SpindleIsOnCW()
> > >
> > > > {
> > >
> > > > Boolean ret = false;
> > >
> > > >
> > >
> > > > UpdateDocument(new Action(delegate()
> > >
> > > > {
> > >
> > > > if (Connected && KMConnected())
> > >
> > > > try
> > >
> > > > {
> > >
> > > > ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1;
> > >
> > > > } catch {}
> > >
> > > > }
> > >
> > > > ));
> > >
> > > > return ret;
> > >
> > > > }
> > >
> > > >
> > >
> > > > ret always returns false, even when GetKFlopBitState returns true.
> > >
> > > >
> > >
> > > > Regards,
> > >
> > > > Ray L.
> > >
> > > >
> > >
> > > >
> > >
> > > > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
> > >
> > > > >
> > >
> > > > > Brad,
> > >
> > > > >
> > >
> > > > > I've been playing with this, and I think I'm starting to get a handle on it, and did find some mistakes where a few things were being called from the wrong thread. It is working better now - not 100%, but close, with a few very brute force fixes just to prove the point.
> > >
> > > > >
> > >
> > > > > So, I think I know how to clean it up.... mostly. I am curious though what is the best approach. I can, of course, always invoke when calling dotNet members from other threads, but I wonder if it wouldn't be cleaner to do the invoke with the methods in my wrapper instead, so the other threads don't need to worry about the housekeeping. Will that work? Would it be higher overhead? It's not clear to me what the overhead of invoking is. Isn't it basically just waiting to get a lock on the target object, which should be fairly low-overhead? Or is there more to it than that?
> > >
> > > > >
> > >
> > > > > Regards,
> > >
> > > > > Ray L.
> > >
> > > > >
> > >
> > > > > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
> > >
> > > > > >
> > >
> > > > > > Brad,
> > >
> > > > > >
> > >
> > > > > > That's exactly what I'm doing. But the question is, *where* do I need to do it. I've done it at what are, to me, the obvious places (all calls from the worker thread, for example), but now have a problem where I didn't before, so I've obviously missed something.
> > >
> > > > > >
> > >
> > > > > > I'm assuming both my "main page" code, and my "wrapper" for dotNet run in the GUI thread. The worker threads should then be invoking for any access to my dotNet wrapper methods, right? But is it necessary to invoke for all of them? Many are doing nothing by reading properties and returning them, without any interaction with the DLLs. I assume those can safely NOT be invoked, right? Can the invokes be "hidden" in my wrapper methods, so they can be called from anywhere?
> > >
> > > > > >
> > >
> > > > > > Regards,
> > >
> > > > > > Ray L.
> > >
> > > > > >
> > >
> > > > > >
> > >
> > > > > > --- In DynoMotion@yahoogroups.com, Brad Murry wrote:
> > >
> > > > > > >
> > >
> > > > > > > Hello Ray
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > > I always used something like this for winforms where there was a
> > >
> > > > > > > possibility of updating controls from a thread other than the main STA
> > >
> > > > > > > Thread.
> > >
> > > > > > >
> > >
> > > > > > > **Note that this method is living inside a UI component like the main form
> > >
> > > > > > > or a usercontrol.
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > > If using .net 2.0 and lower, you have to create a delegate to fire off
> > >
> > > > > > > asynchronously.
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > > public void InvokeUpdateControls()
> > >
> > > > > > >
> > >
> > > > > > > {
> > >
> > > > > > >
> > >
> > > > > > > if (this.InvokeRequired)
> > >
> > > > > > >
> > >
> > > > > > > {
> > >
> > > > > > >
> > >
> > > > > > > this.Invoke(new UpdateControlsDelegate(UpdateControls));
> > >
> > > > > > >
> > >
> > > > > > > }
> > >
> > > > > > >
> > >
> > > > > > > else
> > >
> > > > > > >
> > >
> > > > > > > {
> > >
> > > > > > >
> > >
> > > > > > > UpdateControls();
> > >
> > > > > > >
> > >
> > > > > > > }
> > >
> > > > > > >
> > >
> > > > > > > }
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > > Of course with .net 3.5 and up you get anonymous methods so.
> > >
> > > > > > >
> > >
> > > > > > > public void InvokeUpdateControls()
> > >
> > > > > > >
> > >
> > > > > > > {
> > >
> > > > > > >
> > >
> > > > > > > if (this.InvokeRequired)
> > >
> > > > > > >
> > >
> > > > > > > {
> > >
> > > > > > >
> > >
> > > > > > > this.Invoke(new Action(delegate(){UpdateControls();}));
> > >
> > > > > > >
> > >
> > > > > > > }
> > >
> > > > > > >
> > >
> > > > > > > else
> > >
> > > > > > >
> > >
> > > > > > > {
> > >
> > > > > > >
> > >
> > > > > > > UpdateControls();
> > >
> > > > > > >
> > >
> > > > > > > }
> > >
> > > > > > >
> > >
> > > > > > > }
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > > Good thing the DM libraries are built on 3.5!
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > > -Brad Murry
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > > From: DynoMotion@yahoogroups.com [mailto:DynoMotion@yahoogroups.com] On
> > >
> > > > > > > Behalf Of himykabibble
> > >
> > > > > > > Sent: Sunday, January 13, 2013 5:30 PM
> > >
> > > > > > > To: DynoMotion@yahoogroups.com
> > >
> > > > > > > Subject: [DynoMotion] To Invoke, Or Not To Invoke....
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > >
> > >
> > > > > > > I've got my app converted to use mostly MainStatus, and it at least
> > >
> > > > > > > *appears* I'm getting slightly smoother operation of the DROs. However, I
> > >
> > > > > > > seem to have created a thread hazard or two, a the app now hangs when I do
> > >
> > > > > > > MDI. So, the question is:
> > >
> > > > > > >
> > >
> > > > > > > How do I know when it is necessary to do an invoke? The hangs appear to be
> > >
> > > > > > > occurring withing KMotion.dll, in code that appears to be waiting to obtain
> > >
> > > > > > > a lock. The changes I've made today are limited to code that is interacting
> > >
> > > > > > > with dotNet, and appears to *only* affect MDIs, which are launched from the
> > >
> > > > > > > GUI thread based on on-screen button presses, while most accesses to dotNet
> > >
> > > > > > > are coming from a worker thread. So, I assume it's those two thread stomping
> > >
> > > > > > > on each other causing the problem. The worker thread accesses are always
> > >
> > > > > > > invoked.
> > >
> > > > > > >
> > >
> > > > > > > Any tips on how to figure out what I've screwed up?
> > >
> > > > > > >
> > >
> > > > > > > Regards,
> > >
> > > > > > > Ray L.
> > >
> > > > > > >
> > >
> > > > > >
> > >
> > > > >
> > >
> > > >
> > >
> >
>
|
|
| Group: DynoMotion |
Message: 6505 |
From: himykabibble |
Date: 1/16/2013 |
| Subject: Re: To Invoke, Or Not To Invoke.... |
Brad,
Turns out, this is a non-issue. It was happening because I was using BeginInvoke, instead of Invoke. It's now working fine using the local variables.
BTW - Also discovered in the process that it's easy to create Delegates that take arguments, which will be useful at times.
I think I now have the threading stuff pretty well cleaned up. I put the Invoke code in the functions that are allowed to be called from cross-thread, so the caller does not need to worry about when/where/if to do the Invokes. Might be slightly more overhead in some cases, but it sure simplifies the calling code.
Regards,
Ray L.
--- In DynoMotion@yahoogroups.com, brad murry wrote:
>
> Ahh of course! your variable is out of scope inside the anonymous keeps method (your surrounding function returns before the invoke is complete).
>
> I must have not looked at the whole thing before, as it is quite obvious now. ;)
>
> Either use a delgate, begininvoke it in your invoke block and update the value in the delegate's endinvoke callback or call a function in your anonymous method that sets the value rather than returning a variable value.
>
>
> There are a couple more options that may be more elegant, but are less straightforward.
>
> Sent from my Windows Phone
> ________________________________
> From: himykabibble
> Sent: â1/â14/â2013 12:37 AM
> To: DynoMotion@yahoogroups.com
> Subject: [DynoMotion] Re: To Invoke, Or Not To Invoke....
>
> Brad,
>
> I just stripped down what I pasted into the message. The catch is not empty, and the call is working, and returning the correct value. I believe what is happening is the invoke copies the stack frame, or perhaps just creates a completely new one, executes the code, but does not copy the local variables back to the original frame when the invoke ends, so any local variables that get set in the invoke are lost. If I put the return value into a public variable, then it works correctly. Not ideal, if the function can be called from multiple places simultaneously, but that's not the case here. So I at least have one work-around, though I want to find a cleaner one.
>
> I am NOT doing invokes on methods that are only reading variables, and not communicating with the board. It seems to be working fine like that. Do you think that's OK? Seems to me reads should be perfectly thread-safe, no?
>
> I feel MUCH better about the state of the threading in the app now. It all makes sense, and is much cleaner than it was before. Between me, you and Tom working on various specific pieces of it a year ago, it had some pretty gnarly stuff in it, but I think today I got it pretty well cleaned up, and it's now nice and regular and orderly.
>
> Regards,
> Ray L.
>
> --- In DynoMotion@yahoogroups.com, brad murry wrote:
> >
> >
> > Hey Ray, Just for grins- ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1;
> > > } catch {} In that dead catch, expand it and put a Console.WriteLine("some error"); Then put a breakpoint just to make sure you aren't silently ignoring an exception. I'd also check for this anywhere else you have this type of code. Empty catches are generally bad, even if you do not really care if the exception occurs. I found putting a console write like above or some other logging mechanism has saved me a lot of pain. -Brad Murry
> > To: DynoMotion@yahoogroups.com
> > From: jagboy1964@
> > Date: Mon, 14 Jan 2013 06:03:10 +0000
> > Subject: [DynoMotion] Re: To Invoke, Or Not To Invoke....
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
> > I've got most of it working nicely now, with the invokes done in my dotNet wrapper. It seems to be quite stable, and doing the invokes in the wrapper is a lot simpler. If I can just find a way to make the return values below work, I'll be in business.
> >
> >
> >
> > Sure seems odd to me that I can't seem to write to the ret variable, when everything else seems to work fine.
> >
> >
> >
> > Regards,
> >
> > Ray L.
> >
> >
> >
> > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
> >
> > >
> >
> > > Seems so close.... As a test, I've implemented some of my dotNet wrapper functions so they do the invoke. This seems to be very stable, and works well, except.... I can't get the return values. As an example:
> >
> > >
> >
> > > public Boolean SpindleIsOnCW()
> >
> > > {
> >
> > > Boolean ret = false;
> >
> > >
> >
> > > UpdateDocument(new Action(delegate()
> >
> > > {
> >
> > > if (Connected && KMConnected())
> >
> > > try
> >
> > > {
> >
> > > ret = MainStatus.GetKFlopBitState(KMIO["SpindleCW"].ID) == 1;
> >
> > > } catch {}
> >
> > > }
> >
> > > ));
> >
> > > return ret;
> >
> > > }
> >
> > >
> >
> > > ret always returns false, even when GetKFlopBitState returns true.
> >
> > >
> >
> > > Regards,
> >
> > > Ray L.
> >
> > >
> >
> > >
> >
> > > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
> >
> > > >
> >
> > > > Brad,
> >
> > > >
> >
> > > > I've been playing with this, and I think I'm starting to get a handle on it, and did find some mistakes where a few things were being called from the wrong thread. It is working better now - not 100%, but close, with a few very brute force fixes just to prove the point.
> >
> > > >
> >
> > > > So, I think I know how to clean it up.... mostly. I am curious though what is the best approach. I can, of course, always invoke when calling dotNet members from other threads, but I wonder if it wouldn't be cleaner to do the invoke with the methods in my wrapper instead, so the other threads don't need to worry about the housekeeping. Will that work? Would it be higher overhead? It's not clear to me what the overhead of invoking is. Isn't it basically just waiting to get a lock on the target object, which should be fairly low-overhead? Or is there more to it than that?
> >
> > > >
> >
> > > > Regards,
> >
> > > > Ray L.
> >
> > > >
> >
> > > > --- In DynoMotion@yahoogroups.com, "himykabibble" wrote:
> >
> > > > >
> >
> > > > > Brad,
> >
> > > > >
> >
> > > > > That's exactly what I'm doing. But the question is, *where* do I need to do it. I've done it at what are, to me, the obvious places (all calls from the worker thread, for example), but now have a problem where I didn't before, so I've obviously missed something.
> >
> > > > >
> >
> > > > > I'm assuming both my "main page" code, and my "wrapper" for dotNet run in the GUI thread. The worker threads should then be invoking for any access to my dotNet wrapper methods, right? But is it necessary to invoke for all of them? Many are doing nothing by reading properties and returning them, without any interaction with the DLLs. I assume those can safely NOT be invoked, right? Can the invokes be "hidden" in my wrapper methods, so they can be called from anywhere?
> >
> > > > >
> >
> > > > > Regards,
> >
> > > > > Ray L.
> >
> > > > >
> >
> > > > >
> >
> > > > > --- In DynoMotion@yahoogroups.com, Brad Murry wrote:
> >
> > > > > >
> >
> > > > > > Hello Ray
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > I always used something like this for winforms where there was a
> >
> > > > > > possibility of updating controls from a thread other than the main STA
> >
> > > > > > Thread.
> >
> > > > > >
> >
> > > > > > **Note that this method is living inside a UI component like the main form
> >
> > > > > > or a usercontrol.
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > If using .net 2.0 and lower, you have to create a delegate to fire off
> >
> > > > > > asynchronously.
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > public void InvokeUpdateControls()
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > if (this.InvokeRequired)
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > this.Invoke(new UpdateControlsDelegate(UpdateControls));
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > > else
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > UpdateControls();
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > Of course with .net 3.5 and up you get anonymous methods so.
> >
> > > > > >
> >
> > > > > > public void InvokeUpdateControls()
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > if (this.InvokeRequired)
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > this.Invoke(new Action(delegate(){UpdateControls();}));
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > > else
> >
> > > > > >
> >
> > > > > > {
> >
> > > > > >
> >
> > > > > > UpdateControls();
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > > }
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > Good thing the DM libraries are built on 3.5!
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > -Brad Murry
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > From: DynoMotion@yahoogroups.com [mailto:DynoMotion@yahoogroups.com] On
> >
> > > > > > Behalf Of himykabibble
> >
> > > > > > Sent: Sunday, January 13, 2013 5:30 PM
> >
> > > > > > To: DynoMotion@yahoogroups.com
> >
> > > > > > Subject: [DynoMotion] To Invoke, Or Not To Invoke....
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > >
> >
> > > > > > I've got my app converted to use mostly MainStatus, and it at least
> >
> > > > > > *appears* I'm getting slightly smoother operation of the DROs. However, I
> >
> > > > > > seem to have created a thread hazard or two, a the app now hangs when I do
> >
> > > > > > MDI. So, the question is:
> >
> > > > > >
> >
> > > > > > How do I know when it is necessary to do an invoke? The hangs appear to be
> >
> > > > > > occurring withing KMotion.dll, in code that appears to be waiting to obtain
> >
> > > > > > a lock. The changes I've made today are limited to code that is interacting
> >
> > > > > > with dotNet, and appears to *only* affect MDIs, which are launched from the
> >
> > > > > > GUI thread based on on-screen button presses, while most accesses to dotNet
> >
> > > > > > are coming from a worker thread. So, I assume it's those two thread stomping
> >
> > > > > > on each other causing the problem. The worker thread accesses are always
> >
> > > > > > invoked.
> >
> > > > > >
> >
> > > > > > Any tips on how to figure out what I've screwed up?
> >
> > > > > >
> >
> > > > > > Regards,
> >
> > > > > > Ray L.
> >
> > > > > >
> >
> > > > >
> >
> > > >
> >
> > >
> >
>
|
|
| | | |